package com.mytijian.task.task.process;

import com.alibaba.dubbo.rpc.RpcException;
import com.alibaba.fastjson.JSONObject;
import com.mytijian.base.exception.BizException;
import com.mytijian.base.exception.BizSystemException;
import com.mytijian.task.enums.TaskStatusEnum;
import com.mytijian.task.exception.MtjkTaskProcessException;
import com.mytijian.task.model.SubTask;
import com.mytijian.task.repository.RuningTaskRepository;
import com.mytijian.task.util.IpAddressUtil;
import com.mytijian.task.model.TaskValue;
import com.mytijian.task.enums.FailSceneEnum;
import com.mytijian.task.repository.TaskRepository;
import com.mytijian.task.model.TaskIdentify;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.List;

public class DefaultProcessLifecycle implements ProcessLifecycle {
    private Logger logger = LoggerFactory.getLogger(DefaultProcessLifecycle.class);
    private TaskRepository taskRepository;
    private RuningTaskRepository runingTaskRepository;
    public DefaultProcessLifecycle(RuningTaskRepository runingTaskRepository,  TaskRepository taskRepository) {
        this.taskRepository = taskRepository;
        this.runingTaskRepository = runingTaskRepository;
    }

    @Override
    public void beforeTaskProcess(TaskIdentify taskIdentify) {
        TaskValue taskValue = runingTaskRepository.getByIdentify(IpAddressUtil.getLocalHost(), taskIdentify);
        taskValue.setTaskStuts(TaskStatusEnum.processing.getCode());
        runingTaskRepository.save(taskIdentify, taskValue, IpAddressUtil.getLocalHost());
    }

    @Override
    public void beforeSubTaskProcess(SubTask subTask, TaskIdentify taskIdentify) {
        try {
            TaskValue taskValue = runingTaskRepository.getByIdentify(IpAddressUtil.getLocalHost(), taskIdentify);
            taskValue.setProcessingSubTaskId(subTask.getId());
            runingTaskRepository.save(taskIdentify, taskValue, IpAddressUtil.getLocalHost());
        }catch (Exception e) {
            logger.error("beforeSubTaskProcess 出错 taskIdentify = {} subTask = {} e = {}", taskIdentify.getTaskKey(), JSONObject.toJSONString(subTask), e);
            throw new MtjkTaskProcessException("12", "查询redis出错");
        }

    }

    @Override
    public void afterSubTaskProcess(SubTask subTask, TaskIdentify taskIdentify, Exception e) {
        if (e != null && e instanceof MtjkTaskProcessException) {
            return;
        }
        TaskValue taskValue = runingTaskRepository.getByIdentify(IpAddressUtil.getLocalHost(), taskIdentify);
        taskValue.setCompleteSubTaskId(subTask.getId());
        runingTaskRepository.save(taskIdentify, taskValue, IpAddressUtil.getLocalHost());
        if (e != null) {
            String  failText = e.getMessage();
            FailSceneEnum failSceneEnum = FailSceneEnum.task_exception;
            if (e.getMessage().length() > 2000) {
                failText = e.getMessage().substring(0, 2000);
            }
            if (e instanceof BizException) {
                if (e.getMessage().length() > 2000) {
                    failText = e.getMessage().substring(0, 2000);
                }
                failSceneEnum = FailSceneEnum.biz_biz_exception;
            }
            if ( e instanceof BizSystemException || e instanceof RpcException) {
                if (e.getMessage().length() > 2000) {
                    failText = e.getMessage().substring(0, 2000);
                }
                failSceneEnum = FailSceneEnum.biz_system_exception;
            }
            taskRepository.processFail(subTask.getId(), failSceneEnum.getCode(), failText);
        }
    }


    @Override
    public void taskProcessComplete(TaskIdentify taskIdentify, TaskStatusEnum taskStatusEnum, Exception exception) {
        if (exception != null && exception instanceof  MtjkTaskProcessException) {
            return;
        }
        TaskValue taskValue = runingTaskRepository.getByIdentify(IpAddressUtil.getLocalHost(), taskIdentify);
        // 防止 停止任务之前已经有部分任务完成，机器宕机重启的时候将已完成任务变成停止。
        if (!TaskStatusEnum.getEndStatusInteger().contains(taskValue.getTaskStuts())) {
            taskValue.setTaskStuts(taskStatusEnum.getCode());
            runingTaskRepository.save(taskIdentify, taskValue, IpAddressUtil.getLocalHost());
        }
    }
}
